装饰器

概述

装饰器(Decorator)是Python中一种非常强大的功能,它允许我们在不修改函数或方法代码的情况下,动态地为其添加功能。装饰器本质上是一个函数,它接收另一个函数作为参数,并返回一个新的函数。装饰器在Python中广泛应用于日志记录、权限检查、缓存、事务处理等场景。

理论解释

函数作为一等公民

在Python中,函数是一等公民(First-Class Citizen),这意味着函数可以像其他对象一样被传递、赋值给变量、作为参数传递给其他函数,以及从函数中返回。这种特性为装饰器的实现提供了基础。

装饰器的基本结构

一个装饰器通常由两部分组成:

  1. 装饰器函数:这是一个高阶函数,它接收一个函数作为参数,并返回一个新的函数。
  2. 被装饰的函数:这是我们希望添加额外功能的原始函数。

装饰器的基本结构如下:

def decorator_function(original_function):
    def wrapper_function(*args, **kwargs):
        # 在调用原始函数之前执行的代码
        result = original_function(*args, **kwargs)
        # 在调用原始函数之后执行的代码
        return result
    return wrapper_function

使用装饰器

在Python中,我们可以使用@符号来应用装饰器。例如:

@decorator_function
def my_function():
    pass

这等价于:

def my_function():
    pass

my_function = decorator_function(my_function)

代码示例

示例1:简单的日志装饰器

假设我们希望在每次调用某个函数时,记录一条日志信息。我们可以使用装饰器来实现这一功能。

def log_decorator(func):
    def wrapper(*args, **kwargs):
        print(f"Calling function {func.__name__} with args: {args}, kwargs: {kwargs}")
        result = func(*args, **kwargs)
        print(f"Function {func.__name__} returned: {result}")
        return result
    return wrapper

@log_decorator
def add(a, b):
    return a + b

# 调用被装饰的函数
add(3, 5)

输出:

Calling function add with args: (3, 5), kwargs: {}
Function add returned: 8

示例2:带参数的装饰器

有时,我们希望装饰器能够接收参数。这可以通过创建一个装饰器工厂函数来实现。

def repeat(num_times):
    def decorator_repeat(func):
        def wrapper_repeat(*args, **kwargs):
            for _ in range(num_times):
                result = func(*args, **kwargs)
            return result
        return wrapper_repeat
    return decorator_repeat

@repeat(num_times=3)
def greet(name):
    print(f"Hello, {name}!")

# 调用被装饰的函数
greet("Alice")

输出:

Hello, Alice!
Hello, Alice!
Hello, Alice!

实践练习

练习1:计时装饰器

编写一个装饰器,用于计算函数执行的时间。

import time

def timer_decorator(func):
    def wrapper(*args, **kwargs):
        start_time = time.time()
        result = func(*args, **kwargs)
        end_time = time.time()
        print(f"Function {func.__name__} took {end_time - start_time} seconds to execute.")
        return result
    return wrapper

@timer_decorator
def slow_function():
    time.sleep(2)
    print("Function executed.")

# 调用被装饰的函数
slow_function()

练习2:权限检查装饰器

编写一个装饰器,用于检查用户是否有权限执行某个函数。如果用户没有权限,则抛出一个异常。

def permission_required(permission):
    def decorator_permission(func):
        def wrapper_permission(*args, **kwargs):
            if not has_permission(permission):
                raise PermissionError("You do not have the required permission.")
            return func(*args, **kwargs)
        return wrapper_permission
    return decorator_permission

def has_permission(permission):
    # 模拟权限检查逻辑
    return permission == "admin"

@permission_required("admin")
def delete_user(user_id):
    print(f"User {user_id} deleted.")

# 调用被装饰的函数
try:
    delete_user(123)
except PermissionError as e:
    print(e)

总结

装饰器是Python中一个非常强大的工具,它允许我们在不修改原始函数代码的情况下,为其添加额外的功能。通过掌握装饰器的使用,你可以编写出更加灵活和可维护的代码。希望本教程能够帮助你理解装饰器的基本概念和使用方法,并通过实践练习加深你的理解。